﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Physis.Data.Caching {

    public class CacheManager {

        #region Private Properties

        private Boolean useLocalCachingOnly = true;

        private System.Runtime.Caching.MemoryCache memoryCache = null;

        #endregion 


        #region Public Properties 


        #endregion 


        #region Constructors

        public CacheManager () {

            useLocalCachingOnly = (System.Web.HttpContext.Current == null);

            if (!useLocalCachingOnly) {

                memoryCache = new System.Runtime.Caching.MemoryCache (GetType ().FullName);

            }

            return;

        }

        #endregion 


        #region Public Methods 

        public void CacheObject (String key, Object value, System.Runtime.Caching.CacheItemPolicy policy) {

            if (useLocalCachingOnly) {

                System.Runtime.Caching.CacheItem cacheItem = new System.Runtime.Caching.CacheItem (key, value);

                memoryCache.Set (cacheItem, policy);

            }

            else {

                System.Web.HttpContext.Current.Cache.Remove (key); // REMOVE KEY 

                System.Web.HttpContext.Current.Cache.Remove (key + "_CacheItemPolicy"); // REMOVE POLICY 

                System.Web.HttpContext.Current.Cache.Insert (key, value, null, policy.AbsoluteExpiration.DateTime, policy.SlidingExpiration);

            }

        }

        public void CacheObject (String key, Object value, TimeSpan duration) {

            System.Runtime.Caching.CacheItemPolicy policy = new System.Runtime.Caching.CacheItemPolicy ();

            policy.AbsoluteExpiration = DateTimeOffset.Now.AddSeconds (duration.TotalSeconds);

            policy.SlidingExpiration = duration;

            CacheObject (key, value, policy);

            return;

        }

        public Object GetObject (String key) {

            Object value = null;

            if (useLocalCachingOnly) {

                System.Runtime.Caching.CacheItem cacheItem = memoryCache.GetCacheItem (key);

                value = cacheItem.Value;

            }

            else {

                value = System.Web.HttpContext.Current.Cache[key];

            }


#if DEBUG_CACHING

            if (value == null) {

                System.Diagnostics.Debug.Write ("----> Cache Manager, Miss! [" + key + "]: " + (new System.Diagnostics.StackTrace ().GetFrames ()[1].GetMethod ().Name));

                System.Diagnostics.Debug.Write ("   <-- FROM -->   " + (new System.Diagnostics.StackTrace ().GetFrames ()[2].GetMethod ().Name));

                System.Diagnostics.Debug.Write ("   <-- FROM -->   " + (new System.Diagnostics.StackTrace ().GetFrames ()[3].GetMethod ().Name));

                System.Diagnostics.Debug.Write ("   <-- FROM -->   " + (new System.Diagnostics.StackTrace ().GetFrames ()[4].GetMethod ().Name));

                System.Diagnostics.Debug.WriteLine (String.Empty);

            }

#endif

            return value;

        }

        public void RemoveObject (String key) {

            if (useLocalCachingOnly) {

                memoryCache.Remove (key);

            }

            else {

                System.Web.HttpContext.Current.Cache.Remove (key);

            }

            return;

        }

        public Boolean ContainsKey (String key) {

            Boolean containsKey = false;

            if (useLocalCachingOnly) {

                containsKey = memoryCache.Contains (key);

            }

            else {

                containsKey = (System.Web.HttpContext.Current.Cache[key] != null);

            }

            return containsKey;

        }

        #endregion 

    }

}
